# -*- coding: utf-8 -*-
#
# The Philatelist program is a fork of the OpenNumismat program
# Copyright (c) 2011 - 2024 Vitaly Ignatov (OpenNumismat) <opennumismat@gmail.com>
# Copyright (c) 2021 - 2024 Victor Nabatov (Philatelist) <nabatov.victor@gmail.com>
#

import codecs
import os

try:
    from jinja2 import Environment, FileSystemLoader

except ImportError:
    print('jinja2 module missed. Report engine not available')

from PySide6.QtCore import Qt, QDate, QDir, QFile, QFileInfo, QLocale, QObject
from PySide6.QtGui import QImage

import Philatelist
from Philatelist.Collection.CollectionFields import ImagesFields, TraitsImagesFields
from Philatelist.StampEditor.ImageLabel import ImageLabel
from Philatelist.Tools.Gui import ProgressDialog


def copyFolder(sourceFolder, destFolder):
    sourceDir = QDir(sourceFolder)
    if not sourceDir.exists():
        return

    destDir = QDir(destFolder)
    if destDir.exists():
        destDir.removeRecursively()

    destDir.mkpath(destFolder)
    files = sourceDir.entryList('', QDir.Files)
    for file in files:
        srcName = os.path.join(sourceFolder, file)
        destName = os.path.join(destFolder, file)
        QFile.remove(destName)  # remove if existing
        QFile.copy(srcName, destName)

    files = sourceDir.entryList('', QDir.AllDirs | QDir.NoDotAndDotDot)
    for file in files:
        srcName = os.path.join(sourceFolder, file)
        destName = os.path.join(destFolder, file)
        copyFolder(srcName, destName)


def scanTemplates():
    templates = []
    path = os.path.join(Philatelist.PRJ_PATH, 'Templates')
    sourceDir = QDir(path)
    if sourceDir.exists():
        files = sourceDir.entryList('', QDir.AllDirs | QDir.NoDotAndDotDot)
        for file in files:
            templates.append((file, os.path.join(path, file)))

    return templates


class Report(QObject):

    def __init__(self, model, template, dstPath, parent=None):
        super().__init__(parent)
        self.model = model
        self.srcFolder = template
        self.template = QDir(template).dirName()
        self.img_file_dict = {}
        fileInfo = QFileInfo(dstPath)
        if fileInfo.exists() and fileInfo.isDir():
            self.dstFolder = dstPath
            self.fileName = None
        else:
            self.dstFolder = fileInfo.dir().path()
            self.fileName = fileInfo.fileName()

    def generate(self, indexes, single_file=False):
        if os.path.exists(os.path.join(self.srcFolder, 'stamp.htm')):
            has_item_template = True
        else:
            has_item_template = False
            single_file = True

        self.mapping = {
            'single_file': single_file,
            'date': QLocale.system().toString(QDate.currentDate(), QLocale.LongFormat)
        }
        self.mapping['collection'] = {
            'title': self.model.description.title,
            'description': self.model.description.description,
            'author': self.model.description.author
        }
        if not self.fileName:
            if len(indexes) == 1 and has_item_template:
                self.fileName = "stamp_%d.htm" % self.__getId(indexes[0])
            else:
                self.fileName = "stamps.htm"

        static_files = QFileInfo(self.fileName).baseName() + '_files'
        self.contentDir = os.path.join(self.dstFolder, static_files)
        self.mapping['static_files'] = static_files
        copyFolder(os.path.join(self.srcFolder, 'files'), self.contentDir)
        loader = FileSystemLoader(self.srcFolder)
        self.env = Environment(loader=loader, autoescape=True)
        titles_mapping = {}
        for field in self.model.fields:
            titles_mapping[field.name] = field.title

        self.mapping['titles'] = titles_mapping
        if len(indexes) == 1 and has_item_template:
            self.mapping['record'] = self.__recordMapping(indexes[0])
            dstFile = self.__render('stamp.htm', self.fileName)
        else:
            progressDlg = ProgressDialog(
                self.tr("Generating report"),
                self.tr("Cancel"),
                len(indexes),
                self.parent()
            )
            record_data = []
            for index in indexes:
                progressDlg.step()
                if progressDlg.wasCanceled():
                    return None

                recordMapping = self.__recordMapping(index)
                record_data.append(recordMapping)
                if not single_file:
                    self.mapping['record'] = recordMapping
                    self.__render('stamp.htm', "stamp_%d.htm" % self.__getId(index))

            self.mapping['records'] = record_data
            dstFile = self.__render('stamps.htm', self.fileName)
            progressDlg.reset()

        return dstFile

    def __render(self, template, fileName):
        template = self.env.get_template(template)
        res = template.render(self.mapping)
        dstFile = os.path.join(self.dstFolder, fileName)
        f = codecs.open(dstFile, 'w', 'utf-8')
        f.write(res)
        f.close()
        return dstFile

    def __getId(self, index):
        field_index = self.model.index(index.row(), self.model.fieldIndex('id'))
        return self.model.data(field_index, Qt.UserRole)

    def __recordMapping(self, index):
        record_mapping = {}
        record_mapping['status_raw'] = ''
        record_mapping['cancellation_raw'] = ''
        record_mapping['theme_raw'] = ''
        record_mapping['series_raw'] = ''
        record_mapping['printing_raw'] = ''
        record_mapping['circulation_raw'] = 0
        row = index.row()
        country = ''
        for field in self.model.fields:
            field_index = self.model.index(row, self.model.fieldIndex(field.name))
            value = self.model.data(field_index, Qt.DisplayRole)
            if value is None or value == '':
                record_mapping[field.name] = ''

            if field.name == 'country':
                country = value + '.'

            if field.name == 'image' and self.template == 'Table':
                img_file_title = "%s_%d.%s" % (field.name, self.__getId(index), 'png')
                img_file_name = os.path.join(self.contentDir, img_file_title)
                img_file = open(img_file_name, 'wb')
                img_file.write(value.data())
                img_file.close()
                record_mapping[field.name] = img_file_title

            elif field.name in ImagesFields:
                field_index = self.model.index(row, self.model.fieldIndex(field.name))
                file = self.model.data(field_index, Qt.DisplayRole)
                if file:
                    stamp_image = ImageLabel(field.name)
                    stamp_image.loadFromFile(os.path.join(Philatelist.IMAGES_PATH, file))
                    resolutionX = stamp_image.image.dotsPerMeterX()
                    resolutionY = stamp_image.image.dotsPerMeterX()
                    if resolutionX != 0 or resolutionY != 0:
                        stamp_image.image.setDotsPerMeterX(11811)
                        stamp_image.image.setDotsPerMeterY(11811)
                        scaledImage = stamp_image.image.scaled(
                            stamp_image.image.width() / resolutionX * 11811,
                            stamp_image.image.height() / resolutionY * 11811,
                            Qt.KeepAspectRatio,
                            Qt.SmoothTransformation
                        )
                        if scaledImage.width() > scaledImage.height():
                            record_mapping['img_class'] = 'photoW'
                        else:
                            record_mapping['img_class'] = 'photoH'

                        img_file_title = country + QFileInfo(file).fileName()
                        img_file_name = os.path.join(self.contentDir, img_file_title)
                        scaledImage.save(img_file_name)
                        record_mapping[field.name] = img_file_title

            elif field.name in TraitsImagesFields:
                if self.template == 'Holders':
                    record_mapping[field.name] = ''
                else:
                    field_index = self.model.index(row, self.model.fieldIndex(field.name))
                    file = self.model.data(field_index, Qt.DisplayRole)
                    if file:
                        trait_image = QImage(os.path.join(Philatelist.RESOURCES_PATH, file))
                        img_file_title = QFileInfo(file).fileName()
                        img_file_name = os.path.join(self.contentDir, img_file_title)
                        trait_image.save(img_file_name)
                        record_mapping[field.name] = img_file_title
            else:
                record_mapping[field.name] = value
                if field.name == 'status':
                    record_mapping['status_raw'] = self.model.data(field_index, Qt.UserRole)

                elif field.name == 'cancellation':
                    record_mapping['cancellation_raw'] = self.model.data(field_index, Qt.UserRole)

                elif field.name == 'theme':
                    record_mapping['theme_raw'] = self.model.data(field_index, Qt.UserRole)

                elif field.name == 'series':
                    record_mapping['series_raw'] = self.model.data(field_index, Qt.UserRole)

                elif field.name == 'printing':
                    record_mapping['printing_raw'] = self.model.data(field_index, Qt.UserRole)

                elif field.name == 'circulation':
                    record_mapping['circulation_raw'] = self.model.data(field_index, Qt.UserRole)

        return record_mapping
